package gorm_plugin

import (
	"database/sql"
	"gitee.com/kristas/booting-go/framework/core/log"
	"gitee.com/kristas/booting-go/framework/core/statement/types"
	"gitee.com/kristas/booting-go/framework/data/datasource"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	. "gorm.io/gorm/logger"
	"strings"
	"time"
)

type MySqlDriver struct {
	types.DataSourceDriver `name:"datasource_driver:mysql@gorm" type:"gorm.io/gorm" driver:"gorm.io/driver/mysql"`
	LogConf                *log.Configure
	ConfAdapter            *ConfigAdapter
	Log                    log.Logger `wire:""`
}

func NewMySqlDriver() *MySqlDriver {
	return &MySqlDriver{}
}

func (d *MySqlDriver) Open(properties *datasource.DataSourceProperties) (datasource.DB, error) {
	driver := &datasource.MySqlDriver{}
	conn, err := driver.Open(properties)
	if err != nil {
		return nil, err
	}
	db := conn.(*sql.DB)
	db2, err := d.open(db)
	if err != nil {
		return nil, err
	}
	return db2, nil
}

func (d *MySqlDriver) createConfig() *gorm.Config {
	d.ConfAdapter.Level = d.LogConf.Level
	gormConf := d.ConfAdapter.ToGormConfig()
	gormConf.Logger = NewGormLoggerAdapter(&GormLoggerAdapter{
		log:           d.Log,
		SlowThreshold: 200 * time.Millisecond,
	}).LogMode(parseLevel(d.LogConf.Level))
	return gormConf
}

func (d *MySqlDriver) open(db *sql.DB) (*gorm.DB, error) {
	config := d.createConfig()
	gormDB, err := gorm.Open(mysql.New(mysql.Config{
		Conn: db,
	}), config)
	return gormDB, err
}

func parseLevel(level string) LogLevel {
	switch strings.ToLower(level) {
	case "panic":
		return Silent
	case "fatal", "error":
		return Error
	case "warn", "warning":
		return Warn
	default:
		return Info
	}
}
